home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / workbench werkzeuge / bildschirmschoner / beyondthedark / developer / source / life / life.c next >
C/C++ Source or Header  |  1996-04-07  |  19KB  |  821 lines

  1. /* Life Library */
  2.  
  3. #include <exec/memory.h>
  4. #include <exec/execbase.h>
  5. #include <graphics/gfxbase.h>
  6. #include <intuition/intuitionbase.h>
  7. #include <libraries/iffparse.h>
  8. #include <utility/tagitem.h>
  9.  
  10. #include <clib/macros.h>
  11.  
  12. #define __USE_SYSBASE 42
  13.  
  14. #include <proto/exec.h>
  15. #include <proto/graphics.h>
  16. #include <proto/intuition.h>
  17. #include <proto/utility.h>
  18.  
  19. #include <math.h>
  20. #include <string.h>
  21.  
  22. #include <BTD.h>
  23.  
  24. struct IntuitionBase *IntuitionBase;
  25. struct GfxBase *GfxBase;
  26. struct Library *UtilityBase;
  27.  
  28. /* #define DEBUG YES */
  29.  
  30. #ifdef DEBUG 
  31.  
  32. void KPrintF(char *,...);
  33.  
  34. #define DEBUG_PRINTF(a,b)  KPrintF(a,b);
  35. #define DEBUG_PRINT(a)     KPrintF(a)
  36. #else
  37. #define DEBUG_PRINTF(a,b)
  38. #define DEBUG_PRINT(a)
  39. #endif
  40.  
  41. #define QTAG(o) (BTD_Client+(o))
  42.  
  43. #define LP_ChangePat QTAG(0)
  44. #define LP_Shooter QTAG(1)
  45. #define LP_Cycle   QTAG(2)
  46. #define LP_Colors  QTAG(3)
  47. #define LP_NRow    QTAG(4)
  48.  
  49. #define MAX_CHPT  5000L /* seconds until a new graphic is plotted */
  50. #define MAX_LINES 100L
  51. #define MAX_SHOOT     59L
  52. #define MAX_COLORS 255L
  53. #define MAX_NROW 64L
  54.  
  55. #define DEF_CHPT  1000L
  56. #define DEF_LINES 10L
  57. #define DEF_SHOOT 10L
  58. #define DEF_COLORS 31L
  59. #define DEF_NROW  32L
  60.  
  61. #define    MAXROWS 155
  62. #define MAXCOLS 144
  63. #define TIMEOUT 30
  64.  
  65. #define WHITEPEN (LP->BTDDrawInfo->BDI_Pens[0])
  66.  
  67. struct lifestruct {
  68.     struct BTDDrawInfo *BTDDrawInfo;
  69.     LONG         xs;
  70.     LONG         ys;
  71.     LONG         xb;
  72.     LONG         yb;
  73.     LONG         sub;
  74.     LONG         generation;
  75.     LONG         shooterTime;
  76.     LONG         shooterTimeOut;
  77.     LONG         nrows;
  78.     LONG         ncols;
  79.     LONG         changepat;
  80.     UWORD buffer[(MAXROWS + 2) * (MAXCOLS + 2) + 2];
  81.     UWORD tempbuf[MAXCOLS * 2];
  82.     UWORD lastbuf[MAXCOLS];
  83.     UWORD agebuf[(MAXROWS + 2) * (MAXCOLS + 2)];
  84.     LONG   ls_RandN,ls_RandF,ls_RandI;
  85.     UWORD fates[256];
  86.     UWORD colors;
  87. };
  88.  
  89. #define FindTagData(l,t,d) GetTagData((t),(d),(l))
  90.  
  91. struct BTDInteger LifeIntParams[] =
  92.  {
  93.   LP_ChangePat,"Change Pattern",BTDPT_INTEGER,DEF_CHPT,1L,MAX_CHPT,TRUE,
  94.   LP_Shooter,"Shooter Time",BTDPT_INTEGER,DEF_SHOOT,1L,MAX_SHOOT,TRUE,
  95.   LP_Colors,"Colors",BTDPT_INTEGER,DEF_COLORS,2L,MAX_COLORS,TRUE,
  96.   LP_NRow,"Rows & Cols",BTDPT_INTEGER,DEF_NROW,16L,MAX_NROW,TRUE
  97.  };
  98.  
  99. struct BTDNode *LifeParams[] = 
  100.  {
  101.   &LifeIntParams[0].BI_Node,
  102.   &LifeIntParams[1].BI_Node,
  103.   &LifeIntParams[2].BI_Node,
  104.   &LifeIntParams[3].BI_Node,NULL
  105.  };
  106.  
  107. struct BTDInfo LifeInfo =
  108.  {
  109.   BTDI_Revision,MAKE_ID('L','I','F','E'),
  110.   "Life Blanker","Good old James Conway automaton","Markus Illenseer 1994",
  111.   LifeParams
  112.  };
  113.  
  114. /* library stuff */
  115.  
  116. char MyBlankerName[] = "life.btd";
  117. char MyBlankerID[]   = "Life Blanker V" VERSION "." REVISION " for BTD";
  118.  
  119. LONG MyBlankerLibInit(void)
  120.  
  121. {
  122.  if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L))
  123.   {
  124.    if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L))
  125.     {
  126.      if (UtilityBase=OpenLibrary("utility.library",37L)) return TRUE;
  127.  
  128.      CloseLibrary (&IntuitionBase->LibNode);
  129.     }
  130.    CloseLibrary (&GfxBase->LibNode);
  131.   }
  132.  return FALSE;
  133. }
  134.  
  135. void MyBlankerLibFree(void)
  136.  
  137. {
  138.  CloseLibrary (UtilityBase);
  139.  CloseLibrary (&IntuitionBase->LibNode);
  140.  CloseLibrary (&GfxBase->LibNode);
  141. }
  142.  
  143.  
  144. #define RAND(a,m) (Random(a,m)-(m)/2)
  145.  
  146. void __regargs InitRandom(struct lifestruct *LP,ULONG Instance)
  147. {
  148.  ULONG Time[2];
  149.  
  150.  CurrentTime (&Time[0],&Time[1]);
  151.  LP->ls_RandN=(LONG)Time[0];
  152.  if (Time[1]<1024L) Time[1]|=1;
  153.  else Time[1]>>=10;
  154.  Time[1]^=Instance;
  155.  
  156.  LP->ls_RandF=4*Time[1]+1;
  157.  LP->ls_RandI=2*Time[1]+1;
  158. }
  159.  
  160. WORD __regargs Random(struct lifestruct *LP,WORD Max)
  161. {
  162.  LP->ls_RandN=LP->ls_RandF*LP->ls_RandN+LP->ls_RandI;
  163.  if (LP->ls_RandN<0L) LP->ls_RandN=-LP->ls_RandN;
  164.  
  165.  return (WORD)(LP->ls_RandN%Max);
  166. }
  167.  
  168. struct BTDInfo *QueryMyBlanker(void)
  169. {
  170.  return &LifeInfo;
  171. }
  172.  
  173. /* Buffer stores the data for each cell. Each cell is stored as
  174.  * 8 bits representing the presence of a critter in each of it's
  175.  * surrounding 8 cells. There is an empty row and column around
  176.  * the whole array to allow stores without bounds checking as well
  177.  * as an extra row at the end for the fetches into tempbuf.
  178.  *
  179.  * Tempbuf stores the data for the next two rows so that we know
  180.  * the state of those critter before he was modified by the fate
  181.  * of the critters that have already been processed.
  182.  *
  183.  * Agebuf stores the age of each critter.
  184.  */
  185.  
  186. #define    UPLT    0x01
  187. #define UP    0x02
  188. #define UPRT    0x04
  189. #define LT    0x08
  190. #define RT    0x10
  191. #define DNLT    0x20
  192. #define DN    0x40
  193. #define DNRT    0x80
  194.  
  195. /* Fates is a lookup table for the fate of a critter. The 256
  196.  * entries represent the 256 possible combinations of the 8
  197.  * neighbor cells. Each entry is one of BIRTH (create a cell
  198.  * or leave one alive), SAME (leave the cell alive or dead),
  199.  * or DEATH (kill anything in the cell).
  200.  */
  201. #define BIRTH    0
  202. #define SAME    1
  203. #define DEATH    2
  204.  
  205. static LONG  patterns[][128] = {
  206.     {                /* EIGHT */
  207.     -3, -3, -2, -3, -1, -3,
  208.     -3, -2, -2, -2, -1, -2,
  209.     -3, -1, -2, -1, -1, -1,
  210.     0, 0, 1, 0, 2, 0,
  211.     0, 1, 1, 1, 2, 1,
  212.     0, 2, 1, 2, 2, 2,
  213.     99
  214.     },
  215.     {                /* PULSAR */
  216.     1, 1, 2, 1, 3, 1, 4, 1, 5, 1,
  217.     1, 2, 5, 2,
  218.     99
  219.     },
  220.     {                /* BARBER */
  221.     -7, -7, -6, -7,
  222.     -7, -6, -5, -6,
  223.     -5, -4, -3, -4,
  224.     -3, -2, -1, -2,
  225.     -1, 0, 1, 0,
  226.     1, 2, 3, 2,
  227.     3, 4, 5, 4,
  228.     4, 5, 5, 5,
  229.     99
  230.     },
  231.     {                /* HERTZ */
  232.     -2, -6, -1, -6,
  233.     -2, -5, -1, -5,
  234.     -7, -3, -6, -3, -2, -3, -1, -3, 0, -3, 1, -3, 5, -3, 6, -3,
  235.     -7, -2, -5, -2, -3, -2, 2, -2, 4, -2, 6, -2,
  236.     -5, -1, -3, -1, -2, -1, 2, -1, 4, -1,
  237.     -7, 0, -5, 0, -3, 0, 2, 0, 4, 0, 6, 0,
  238.     -7, 1, -6, 1, -2, 1, -1, 1, 0, 1, 1, 1, 5, 1, 6, 1,
  239.     -2, 3, -1, 3,
  240.     -2, 4, -1, 4,
  241.     99
  242.     },
  243.     {                /* TUMBLER */
  244.     -6, -6, -5, -6, 6, -6, 7, -6,
  245.     -6, -5, -5, -5, 6, -5, 7, -5,
  246.     -5, 5, 6, 5,
  247.     -7, 6, -5, 6, 6, 6, 8, 6,
  248.     -7, 7, -5, 7, 6, 7, 8, 7,
  249.     -7, 8, -6, 8, 7, 8, 8, 8,
  250.     99
  251.     },
  252.     {                /* PERIOD4 */
  253.     -5, -8, -4, -8,
  254.     -7, -7, -5, -7,
  255.     -8, -6, -2, -6,
  256.     -7, -5, -3, -5, -2, -5,
  257.     -5, -3, -3, -3,
  258.     -4, -2,
  259.     99
  260.     },
  261.     {                /* PERIOD5 */
  262.     -5, -8, -4, -8,
  263.     -6, -7, -3, -7,
  264.     -7, -6, -2, -6,
  265.     -8, -5, -1, -5,
  266.     -8, -4, -1, -4,
  267.     -7, -3, -2, -3,
  268.     -6, -2, -3, -2,
  269.     -5, -1, -4, -1,
  270.     99
  271.     },
  272.     {                /* PERIOD6 */
  273.     -4, -8, -3, -8,
  274.     -8, -7, -7, -7, -5, -7,
  275.     -8, -6, -7, -6, -4, -6, -1, -6,
  276.     -3, -5, -1, -5,
  277.     -2, -4,
  278.     -3, -2, -2, -2,
  279.     -3, -1, -2, -1,
  280.     99
  281.     },
  282.     {                /* PINWHEEL */
  283.     -4, -8, -3, -8,
  284.     -4, -7, -3, -7,
  285.     -4, -5, -3, -5, -2, -5, -1, -5,
  286.     -5, -4, -3, -4, 0, -4, 2, -4, 3, -4,
  287.     -5, -3, -1, -3, 0, -3, 2, -3, 3, -3,
  288.     -8, -2, -7, -2, -5, -2, -2, -2, 0, -2,
  289.     -8, -1, -7, -1, -5, -1, 0, -1,
  290.     -4, 0, -3, 0, -2, 0, -1, 0,
  291.     -2, 2, -1, 2,
  292.     -2, 3, -1, 3,
  293.     99
  294.     },
  295.     {                /* ] */
  296.     -1, -1, 0, -1, 1, -1,
  297.     0, 0, 1, 0,
  298.     -1, 1, 0, 1, 1, 1,
  299.     99
  300.     },
  301.     {                /* cc: */
  302.     -3, -1, -2, -1, -1, -1, 1, -1, 2, -1, 3, -1,
  303.     -3, 0, -2, 0, 1, 0, 2, 0,
  304.     -3, 1, -2, 1, -1, 1, 1, 1, 2, 1, 3, 1,
  305.     99
  306.     },
  307.     {                /* DOLBY */
  308.     -3, -1, -2, -1, -1, -1, 1, -1, 2, -1, 3, -1,
  309.     -3, 0, -2, 0, 2, 0, 3, 0,
  310.     -3, 1, -2, 1, -1, 1, 1, 1, 2, 1, 3, 1,
  311.     99
  312.     },
  313.     {                /* HORIZON */
  314.     -15, 0, -14, 0, -13, 0, -12, 0, -11, 0,
  315.     -10, 0, -9, 0, -8, 0, -7, 0, -6, 0,
  316.     -5, 0, -4, 0, -3, 0, -2, 0, -1, 0,
  317.     4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
  318.     9, 0, 8, 0, 7, 0, 6, 0, 5, 0,
  319.     14, 0, 13, 0, 12, 0, 11, 0, 10, 0,
  320.     99
  321.     },
  322.     {                /* SHEAR */
  323.     -7, -2, -6, -2, -5, -2, -4, -2, -3, -2,
  324.     -2, -2, -1, -2, 0, -2, 1, -2, 2, -2,
  325.     -5, -1, -4, -1, -3, -1, -2, -1, -1, -1,
  326.     0, -1, 1, -1, 2, -1, 3, -1, 4, -1,
  327.     -3, 0, -2, 0, -1, 0, 0, 0, 1, 0,
  328.     2, 0, 3, 0, 4, 0, 5, 0, 6, 0,
  329.     -10, 1, -9, 1, -8, 1, -7, 1, -6, 1,
  330.     -5, 1, -4, 1, -3, 1, -2, 1, -1, 1,
  331.     -10, 2, -9, 2, -8, 2, -7, 2, -6, 2,
  332.     -5, 2, -4, 2, -3, 2, -2, 2, -1, 2,
  333.     99
  334.     },
  335.     {                /* VERTIGO */
  336.     0, -7,
  337.     0, -6,
  338.     0, -5,
  339.     0, -4,
  340.     0, -3,
  341.     0, -2,
  342.     0, -1,
  343.     0, 0,
  344.     0, 7,
  345.     0, 6,
  346.     0, 5,
  347.     0, 4,
  348.     0, 3,
  349.     0, 2,
  350.     0, 1,
  351.     99
  352.     },
  353.     {                /* CROSSBAR */
  354.     -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
  355.     99
  356.     },
  357.     {                /* GOALPOSTS */
  358.     -8, -7, 8, -7,
  359.     -8, -6, 8, -6,
  360.     -8, -5, 8, -5,
  361.     -8, -4, 8, -4,
  362.     -8, -3, 8, -3,
  363.     -8, -2, 8, -2,
  364.     -8, -1, 8, -1,
  365.     -8, 0, 8, 0,
  366.     -8, 1, 8, 1,
  367.     -8, 2, 8, 2,
  368.     -8, 3, 8, 3,
  369.     -8, 4, 8, 4,
  370.     -8, 5, 8, 5,
  371.     -8, 6, 8, 6,
  372.     -8, 7, 8, 7,
  373.     99
  374.     },
  375.     {                /* \ */
  376.     -8, -8, -7, -8,
  377.     -7, -7, -6, -7,
  378.     -6, -6, -5, -6,
  379.     -5, -5, -4, -5,
  380.     -4, -4, -3, -4,
  381.     -3, -3, -2, -3,
  382.     -2, -2, -1, -2,
  383.     -1, -1, 0, -1,
  384.     0, 0, 1, 0,
  385.     1, 1, 2, 1,
  386.     2, 2, 3, 2,
  387.     3, 3, 4, 3,
  388.     4, 4, 5, 4,
  389.     5, 5, 6, 5,
  390.     6, 6, 7, 6,
  391.     7, 7, 8, 7,
  392.     99
  393.     },
  394.     {                /* LABYRINTH */
  395.     -4, -4, -3, -4, -2, -4, -1, -4, 0, -4, 1, -4, 2, -4, 3, -4, 4, -4,
  396.     -4, -3, 0, -3, 4, -3,
  397.     -4, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 4, -2,
  398.     -4, -1, -2, -1, 2, -1, 4, -1,
  399.     -4, 0, -2, 0, -1, 0, 0, 0, 1, 0, 2, 0, 4, 0,
  400.     -4, 1, -2, 1, 2, 1, 4, 1,
  401.     -4, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2, 4, 2,
  402.     -4, 3, 0, 3, 4, 3,
  403.     -4, 4, -3, 4, -2, 4, -1, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4,
  404.     99
  405.     },
  406.     {/* ill */
  407.      -5, -5, -3, -5, -1, -5,
  408.      -5, -4, -3, -4, -1, -4,
  409.              -3, -3, -1, -3,
  410.      -5, -2, -3, -2, -1, -2,
  411.      -5, -1, -3, -1, -1, -1,
  412.      -5,  0, -3,  0, -1,  0,
  413.      99
  414.     },
  415.     {/* r-pentomino, extracted from the SF-book 'Ox' from Piers Anthony*/
  416.               0, -1,  1, -1,
  417.      -1,  0,  0,  0,
  418.               0,  1,
  419.      99
  420.     }
  421.  
  422. };
  423.  
  424. #define NPATS    (sizeof patterns / sizeof patterns[0])
  425.  
  426. void drawcell(struct lifestruct *LP,LONG row, LONG col)
  427. {
  428.     WORD x1,x2,y1,y2;
  429.  
  430.     SetAPen(LP->BTDDrawInfo->BDI_RPort,WHITEPEN);
  431.     if (LP->colors > 2) {
  432.     UWORD *loc = LP->buffer + ((row + 1) * (LP->ncols + 2)) + col + 1;
  433.     UWORD *ageptr = LP->agebuf + (loc - LP->buffer);
  434.     UWORD age = *ageptr;
  435.  
  436.     /* if we aren't up to blue yet, then keep aging the cell. */
  437.     if (age < (((LP->colors+2)*7)/10))
  438.         ++age;
  439.  
  440.         SetAPen(LP->BTDDrawInfo->BDI_RPort,LP->BTDDrawInfo->BDI_Pens[age]);
  441.     *ageptr = age;
  442.     }
  443.  
  444.     x1=(WORD)(LP->xb + LP->xs * col)-LP->sub;
  445.     y1=(WORD)(LP->yb + LP->ys * row)-LP->sub;
  446.     x2=(WORD)(LP->xs)-LP->sub-1+x1;
  447.     y2=(WORD)(LP->ys)-LP->sub-1+y1;
  448.  
  449.     if(x2<x1) x2=x1;
  450.     if(y2<y1) y2=y1;
  451.  
  452.     if(x1<0) x1=0;
  453.     if(y1<0) y1=0;
  454.  
  455.     RectFill(LP->BTDDrawInfo->BDI_RPort,x1,y1,x2,y2);
  456. }
  457.  
  458.  
  459. void erasecell(struct lifestruct *LP,LONG row, LONG col)
  460. {
  461.     WORD x1,x2,y1,y2;
  462.  
  463.     x1=(WORD)(LP->xb + LP->xs * col)-LP->sub;
  464.     y1=(WORD)(LP->yb + LP->ys * row)-LP->sub;
  465.     x2=(WORD)(LP->xs)-LP->sub-1+x1;
  466.     y2=(WORD)(LP->ys)-LP->sub-1+y1;
  467.  
  468.     if(x2<x1) x2=x1;
  469.     if(y2<y1) y2=y1;
  470.  
  471.     if(x1<0) x1=0;
  472.     if(y1<0) y1=0;
  473.  
  474.     SetAPen(LP->BTDDrawInfo->BDI_RPort,BTD_BgPen);
  475.     RectFill(LP->BTDDrawInfo->BDI_RPort,x1,y1,x2,y2);
  476. }
  477.  
  478.  
  479. void spawn(struct lifestruct *LP,UWORD *loc)
  480. {
  481.     UWORD *ulloc, *ucloc, *urloc, *clloc, *crloc, *llloc, *lcloc, *lrloc,
  482.                *arloc;
  483.     LONG         off, row, col, lastrow;
  484.  
  485.     lastrow = (LP->nrows) * (LP->ncols + 2);
  486.     off = loc - LP->buffer;
  487.     col = off % (LP->ncols + 2);
  488.     row = (off - col) / (LP->ncols + 2);
  489.     ulloc = loc - LP->ncols - 3;
  490.     ucloc = loc - LP->ncols - 2;
  491.     urloc = loc - LP->ncols - 1;
  492.     clloc = loc - 1;
  493.     crloc = loc + 1;
  494.     arloc = loc + 1;
  495.     llloc = loc + LP->ncols + 1;
  496.     lcloc = loc + LP->ncols + 2;
  497.     lrloc = loc + LP->ncols + 3;
  498.     if (row == 1) {
  499.     ulloc += lastrow;
  500.     ucloc += lastrow;
  501.     urloc += lastrow;
  502.     }
  503.     if (row == LP->nrows) {
  504.     llloc -= lastrow;
  505.     lcloc -= lastrow;
  506.     lrloc -= lastrow;
  507.     }
  508.     if (col == 1) {
  509.     ulloc += LP->ncols;
  510.     clloc += LP->ncols;
  511.     llloc += LP->ncols;
  512.     }
  513.     if (col == LP->ncols) {
  514.     urloc -= LP->ncols;
  515.     crloc -= LP->ncols;
  516.     lrloc -= LP->ncols;
  517.     }
  518.     *ulloc |= UPLT;
  519.     *ucloc |= UP;
  520.     *urloc |= UPRT;
  521.     *clloc |= LT;
  522.     *crloc |= RT;
  523.     *arloc |= RT;
  524.     *llloc |= DNLT;
  525.     *lcloc |= DN;
  526.     *lrloc |= DNRT;
  527.  
  528.     *(LP->agebuf + (loc - LP->buffer)) = 0;
  529. }
  530.  
  531.  
  532. void kill(struct lifestruct *LP,UWORD *loc)
  533. {
  534.     UWORD *ulloc, *ucloc, *urloc, *clloc, *crloc, *llloc, *lcloc,
  535.                *lrloc, *arloc;
  536.     LONG         off, row, col, lastrow;
  537.  
  538.     lastrow = (LP->nrows) * (LP->ncols + 2);
  539.     off = loc - LP->buffer;
  540.     col = off % (LP->ncols + 2);
  541.     row = (off - col) / (LP->ncols + 2);
  542.     ulloc = loc - LP->ncols - 3;
  543.     ucloc = loc - LP->ncols - 2;
  544.     urloc = loc - LP->ncols - 1;
  545.     clloc = loc - 1;
  546.     crloc = loc + 1;
  547.     arloc = loc + 1;
  548.     llloc = loc + LP->ncols + 1;
  549.     lcloc = loc + LP->ncols + 2;
  550.     lrloc = loc + LP->ncols + 3;
  551.     if (row == 1) {
  552.     ulloc += lastrow;
  553.     ucloc += lastrow;
  554.     urloc += lastrow;
  555.     }
  556.     if (row == LP->nrows) {
  557.     llloc -= lastrow;
  558.     lcloc -= lastrow;
  559.     lrloc -= lastrow;
  560.     }
  561.     if (col == 1) {
  562.     ulloc += LP->ncols;
  563.     clloc += LP->ncols;
  564.     llloc += LP->ncols;
  565.     }
  566.     if (col == LP->ncols) {
  567.     urloc -= LP->ncols;
  568.     crloc -= LP->ncols;
  569.     lrloc -= LP->ncols;
  570.     }
  571.     *ulloc &= ~UPLT;
  572.     *ucloc &= ~UP;
  573.     *urloc &= ~UPRT;
  574.     *clloc &= ~LT;
  575.     *crloc &= ~RT;
  576.     *arloc &= ~RT;
  577.     *llloc &= ~DNLT;
  578.     *lcloc &= ~DN;
  579.     *lrloc &= ~DNRT;
  580. }
  581.  
  582.  
  583. void setcell(struct lifestruct *LP,LONG row, LONG col)
  584. {
  585.     UWORD *loc;
  586.  
  587.     loc = LP->buffer + ((row + 1) * (LP->ncols + 2)) + col + 1;
  588.     spawn(LP,loc);
  589.     drawcell(LP,row, col);
  590. }
  591.  
  592.  
  593. void init_fates(struct lifestruct *LP)
  594. {
  595.     LONG         i, bits, neighbors;
  596.  
  597.     for (i = 0; i < 256; i++) {
  598.     neighbors = 0;
  599.     for (bits = i; bits; bits &= (bits - 1))
  600.         neighbors++;
  601.     if (neighbors == 3)
  602.         LP->fates[i] = BIRTH;
  603.     else if (neighbors == 2)
  604.         LP->fates[i] = SAME;
  605.     else
  606.         LP->fates[i] = DEATH;
  607.     }
  608. }
  609.  
  610. void InitNewLife(struct lifestruct *LP)
  611. {
  612.     LONG row, col;
  613.     LONG *patptr;
  614.     ULONG Time[2];
  615.  
  616.     LP->generation = 0;
  617.     CurrentTime (&Time[0],&Time[1]);
  618.     LP->shooterTimeOut = Time[0];
  619.  
  620.     SetAPen(LP->BTDDrawInfo->BDI_RPort,BTD_BgPen);
  621.     RectFill(LP->BTDDrawInfo->BDI_RPort,LP->BTDDrawInfo->BDI_Left,
  622.                                         LP->BTDDrawInfo->BDI_Top,
  623.                                         LP->BTDDrawInfo->BDI_Width+LP->BTDDrawInfo->BDI_Left-1,
  624.                                         LP->BTDDrawInfo->BDI_Height+LP->BTDDrawInfo->BDI_Top-1);
  625.  
  626.  
  627.     bzero(LP->buffer, sizeof(LP->buffer));
  628.     patptr = &patterns[Random(LP,NPATS)][0];
  629.     while ((col = *patptr++) != 99) {
  630.     row = *patptr++;
  631.     col += LP->ncols / 2;
  632.     row += LP->nrows / 2;
  633.     setcell(LP,row, col);
  634.     }
  635. }
  636.  
  637. struct lifestruct *InitMyBlanker(struct TagItem *TagList)
  638. {
  639.  
  640.  LONG ChangePat,Shoot,Colors;
  641.  struct lifestruct *LP;
  642.  struct BTDDrawInfo *BTDDrawInfo;
  643.  ULONG *Error,Dummy,Index,Instance;
  644.  LONG Step;
  645.  
  646.  LONG row, col, NRow;
  647.  LONG *patptr;
  648.  ULONG Time[2];
  649.  
  650.  if ((BTDDrawInfo=(struct BTDDrawInfo *)
  651.                    FindTagData(TagList,BTD_DrawInfo,NULL))==NULL) return NULL;
  652.  Error=(LONG *)FindTagData(TagList,BTD_Error,(ULONG)&Dummy);
  653.  if ((LP=AllocVec(sizeof(struct lifestruct),MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  654.   {
  655.    *Error=BTDERR_Memory;
  656.    return NULL;
  657.   }
  658.  
  659.  ChangePat=FindTagData(TagList,LP_ChangePat,DEF_CHPT);
  660.  Instance=FindTagData(TagList,BTD_Instance,0L);
  661.  Shoot=FindTagData(TagList,LP_Shooter,DEF_SHOOT);
  662.  Colors=FindTagData(TagList,LP_Colors,DEF_COLORS);
  663.  NRow=FindTagData(TagList,LP_NRow,DEF_NROW);
  664.  
  665.  LP->BTDDrawInfo=BTDDrawInfo;
  666.  
  667.  InitRandom(LP,Instance);
  668.  CurrentTime (&Time[0],&Time[1]);
  669.  
  670.  init_fates(LP);
  671.  
  672.  LP->generation = 0;
  673.  LP->shooterTime = Shoot;
  674.  LP->shooterTimeOut = Time[0];
  675.  LP->colors=Colors;
  676.  
  677.  LP->changepat=ChangePat;
  678.  
  679.  LP->ncols = NRow;
  680.  LP->nrows = NRow;
  681.  LP->xs = (BTDDrawInfo->BDI_Width-1) / LP->ncols;
  682.  LP->ys = (BTDDrawInfo->BDI_Height-1) / LP->nrows;
  683.  LP->xb = BTDDrawInfo->BDI_Left+1+(BTDDrawInfo->BDI_Width - LP->xs * LP->ncols) / 2;
  684.  LP->yb = BTDDrawInfo->BDI_Top+(BTDDrawInfo->BDI_Height - LP->ys * LP->nrows) / 2;
  685.  LP->sub= (LP->xs<4?1:2);
  686.  
  687.  bzero(LP->buffer, sizeof(LP->buffer)); 
  688.  patptr = &patterns[Random(LP,NPATS)][0];
  689.  while ((col = *patptr++) != 99) {
  690.     row = *patptr++;
  691.     col += LP->ncols / 2;
  692.     row += LP->nrows / 2;
  693.     setcell(LP,row, col);
  694.     }
  695.  
  696.  Step=(256/LP->colors);
  697.  
  698.  for(Index=0; Index<LP->colors; Index++)
  699.   {
  700.    static UWORD r,g,b;
  701.  
  702.    if((r=(Step*Index))>255) r=255;
  703.    if((g=(128-Step*Index>128?(Step*Index)*(-1):(Step*Index)))>255) g=255;
  704.    if((b=(255-Step*Index))>255) b=255; 
  705.  
  706.    BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[Index]]=r;
  707.    BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[Index]]=g;
  708.    BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[Index]]=b;
  709.   }
  710.  
  711.  BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[0]]=0;
  712.  BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[0]]=0;
  713.  BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[0]]=255;
  714.  
  715.  BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[1]]=255;
  716.  BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[1]]=0;
  717.  BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[1]]=0;
  718.  
  719.  BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[LP->colors-1]]=16;
  720.  BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[LP->colors-1]]=0;
  721.  BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[LP->colors-1]]=0;
  722.  
  723.  for(Index=0; Index<LP->colors; Index++)
  724.   BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[Index]]=TRUE;
  725.  
  726.  LP->BTDDrawInfo=BTDDrawInfo;
  727.  
  728.  return LP;
  729.  
  730. }
  731.  
  732.  
  733. void EndMyBlanker(struct lifestruct *LP)
  734. {
  735. DEBUG_PRINT("Life: FreeMem\n");
  736.  FreeVec (LP);
  737. }
  738.  
  739.  
  740. void AnimMyBlanker(struct lifestruct *LP)
  741. {
  742.     UWORD *loc, *temploc, *lastloc;
  743.     LONG         row, col;
  744.     UWORD fate;
  745.     ULONG Time[2];
  746.  
  747.     loc = LP->buffer + LP->ncols + 2 + 1;
  748.     temploc = LP->tempbuf;
  749.     /* copy the first 2 rows to the tempbuf */
  750.     bcopy(loc, temploc, LP->ncols);
  751.     bcopy(loc + LP->ncols + 2, temploc + LP->ncols, LP->ncols);
  752.  
  753.     lastloc = LP->lastbuf;
  754.     /* copy the last row to another buffer for wraparound */
  755.     bcopy(loc + ((LP->nrows - 1) * (LP->ncols + 2)), lastloc, LP->ncols);
  756.  
  757.     for (row = 0; row < LP->nrows; ++row) {
  758.     for (col = 0; col < LP->ncols; ++col) {
  759.         fate = LP->fates[*temploc];
  760.         *temploc = (row == (LP->nrows - 3)) ?
  761.         *(lastloc + col) :
  762.         *(loc + (LP->ncols + 2) * 2);
  763.         switch (fate) {
  764.         case BIRTH:
  765.         if (!(*(loc + 1) & RT)) {
  766.             spawn(LP,loc);
  767.         }
  768.         /* NO BREAK */
  769.         case SAME:
  770.         if (*(loc + 1) & RT) {
  771.             drawcell(LP,row, col);
  772.         }
  773.         break;
  774.         case DEATH:
  775.         if (*(loc + 1) & RT) {
  776.             kill(LP,loc);
  777.             erasecell(LP,row, col);
  778.         }
  779.         break;
  780.         }
  781.         loc++;
  782.         temploc++;
  783.     }
  784.     loc += 2;
  785.     if (temploc >= LP->tempbuf + LP->ncols * 2)
  786.         temploc = LP->tempbuf;
  787.     }
  788.  
  789.     if (++LP->generation > LP->changepat)
  790.     InitNewLife(LP);
  791.  
  792.     /*
  793.      * generate a randomized shooter aimed roughly toward the center of the
  794.      * screen after timeout.
  795.      */
  796.     CurrentTime (&Time[0],&Time[1]);
  797.     if (LP->shooterTime>0 && Time[0]-LP->shooterTimeOut > LP->shooterTime) {
  798.     LONG         hsp = Random(LP,(LP->ncols - 5)) + 3;
  799.     LONG         vsp = Random(LP,(LP->nrows - 5)) + 3;
  800.     LONG         hoff = 1;
  801.     LONG         voff = 1;
  802.     if (vsp > LP->nrows / 2)
  803.         voff = -1;
  804.     if (hsp > LP->ncols / 2)
  805.         hoff = -1;
  806.     setcell(LP,vsp + 0 * voff, hsp + 2 * hoff);
  807.     setcell(LP,vsp + 1 * voff, hsp + 2 * hoff);
  808.     setcell(LP,vsp + 2 * voff, hsp + 2 * hoff);
  809.     setcell(LP,vsp + 2 * voff, hsp + 1 * hoff);
  810.     setcell(LP,vsp + 1 * voff, hsp + 0 * hoff);
  811.         CurrentTime (&Time[0],&Time[1]);
  812.     LP->shooterTimeOut = Time[0];
  813.     }
  814. }
  815.  
  816. ULONG PenCountMyBlanker(struct TagItem *TagList)
  817.  
  818. {
  819.  return FindTagData(TagList,LP_Colors,DEF_COLORS);
  820. }
  821.